﻿using System;
using System.Net;
using System.Windows;
using System.Collections.Generic;
using System.Windows.Resources;
using System.Xml;
using System.IO;
using System.Reflection;
using System.Windows.Browser;

namespace SamplesShow
{
    public class SamplesCollection :Dictionary<string, List<TreeItem_Sample>>
    {
        Queue<Uri> LoadPartList = new Queue<Uri>();
        static SamplesCollection current;
        public static SamplesCollection Current
        {
            get
            {
                if (current == null)
                    current = new SamplesCollection();
                return current;
            }
        }
        private SamplesCollection()
        {
            var s = App.Current.Host.Source.AbsoluteUri;
            var htmlhost = s.Substring(0, s.LastIndexOf("ClientBin"));
            List<TreeItem_Sample> samplelist;
            TreeItem_Sample sample;

            samplelist = new List<TreeItem_Sample>();
            sample = new TreeItem_Sample("Sample01_Base","Sample_1","这是最简单的例子");
            sample.Header = "基本图片NImage";
            samplelist.Add(sample);
            sample = new TreeItem_Sample("Sample01_Base", "Sample_2", "该例子展示简单的移动处理方法");
            sample.Header = "简单移动NImageM";
            samplelist.Add(sample);
            sample = new TreeItem_Sample("Sample01_Base", "Sample_3", "该例子显示了如何使用快捷键");
            sample.Header = "快捷键";
            samplelist.Add(sample);
            this.Add("基本(Basic)", samplelist);

            samplelist = new List<TreeItem_Sample>();
            sample = new TreeItem_Sample("Sample02_Role", "Sample_1", "这是一个基本的精灵例子，使用类SpiritLoader下载资源文件并创建NSpirit");
            sample.Header = "基本的精灵";
            samplelist.Add(sample);
            sample = new TreeItem_Sample("Sample02_Role", "Sample_2", "一个简单的NPC示例，使用了简要的角色精灵类实现");
            sample.Header = "简单的NPC";
            samplelist.Add(sample);
            sample = new TreeItem_Sample("Sample02_Role", "Sample_3", "这个精灵带有了多个动作，此例子演示了如何读取和使用这些动画动作");
            sample.Header = "动作演示";
            samplelist.Add(sample);
            sample = new TreeItem_Sample("Sample02_Role", "Sample_4", "复杂的角色，这个角色有上身和下身之分，通过Role.Parts组合在一起，并可以统一控制动画");
            sample.Header = "复杂角色";
            samplelist.Add(sample);
            sample = new TreeItem_Sample("Sample02_Role", "Sample_5", "通过键盘输入控制Hero移动行走，并显示正确的动画，操作：A 向左走；D向右走；J开枪攻击");
            sample.Header = "可控角色";
            samplelist.Add(sample);
            sample = new TreeItem_Sample("Sample02_Role", "Sample_6", "通过键盘输入控制Hero移动并攻击不断刷出的僵尸怪物，操作：A 向左走；D向右走；J开枪攻击");
            sample.Header = "战斗小游戏";
            sample.IsRemoveAndDestroy = true;
            samplelist.Add(sample);
            sample = new TreeItem_Sample("Sample02_Role", "Sample_7", "这是一个标准角色类的演示，按照标准的角色规格读取并解析资源，该资源方式带了两个状态，可以依据自己的需求拓展");
            sample.Header = "标准角色";
            sample.IsRemoveAndDestroy = true;
            samplelist.Add(sample);
            sample = new TreeItem_Sample("Sample02_Role", "Sample_8", "这是一个标准角色类的控制演示，可以通过鼠标点击屏幕指定行走目标，内部实现状态切换");
            sample.Header = "可控标准角色";
            sample.IsRemoveAndDestroy = true;
            samplelist.Add(sample);
            
            this.Add("角色(Role)", samplelist);
            samplelist = new List<TreeItem_Sample>();
            sample = new TreeItem_Sample("Sample03_Scene", "Sample_1", "控件方式的场景载入，利用Blend制作地图，并将资源包含在xap包里");
            sample.Header = "第一种控件方式的场景载入";
            sample.BlankUri = new Uri(htmlhost + "Sample03_SceneTestPage.html?index=1", UriKind.Absolute);
            samplelist.Add(sample);

            sample = new TreeItem_Sample("Sample03_Scene", "Sample_2", "XAML的静态数据方式场景地图使用，资源不包含在包内");
            sample.Header = "第二种XAML方式的场景载入";
            sample.BlankUri = new Uri(htmlhost + "Sample03_SceneTestPage.html?index=2", UriKind.Absolute);
            samplelist.Add(sample);

            sample = new TreeItem_Sample("Sample03_Scene", "Sample_3", "角色和场景结合的例子");
            sample.Header = "角色+场景";
            sample.BlankUri = new Uri(htmlhost + "Sample03_SceneTestPage.html?index=3", UriKind.Absolute);
            samplelist.Add(sample);

            sample = new TreeItem_Sample("Sample03_Scene", "Sample_4", "带有脚本逻辑的空间式地图，复合型场景例子");
            sample.Header = "复合型场景实例";
            sample.BlankUri = new Uri(htmlhost + "Sample03_SceneTestPage.html?index=4", UriKind.Absolute);
            samplelist.Add(sample);

            
            this.Add("场景(Scene)", samplelist);
            LoadPartList.Enqueue(new Uri("Sample01_Base.xap", UriKind.Relative));
            LoadPartList.Enqueue(new Uri("Sample02_Role.xap", UriKind.Relative));
            LoadPartList.Enqueue(new Uri("Sample03_Scene.xap", UriKind.Relative));

        }

        #region 初始化及下载
        public void BeginInitialize()
        {
            WebClient webclient = new WebClient();
            webclient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webclient_DownloadProgressChanged);
            webclient.OpenReadCompleted += new OpenReadCompletedEventHandler(webclient_OpenReadCompleted);
            var s = LoadPartList.Dequeue();
            webclient.OpenReadAsync(s, s.ToString());
        }
        void webclient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            (sender as WebClient).OpenReadCompleted -= webclient_OpenReadCompleted;
            (sender as WebClient).DownloadProgressChanged -= webclient_DownloadProgressChanged;
            LoadAssemblyFromXap(e.Result);
            if (LoadPartList.Count <= 0)
            {
                
                if (OpenReadCompleted != null)
                    OpenReadCompleted(sender, e);
            }
            else
            {
                WebClient webclient = new WebClient();
                webclient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webclient_DownloadProgressChanged);
                webclient.OpenReadCompleted += new OpenReadCompletedEventHandler(webclient_OpenReadCompleted);
                var s = LoadPartList.Dequeue();
                webclient.OpenReadAsync(s, s.ToString());
            }

        }

        void webclient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            if (DownloadProgressChanged != null)
                DownloadProgressChanged(sender, e);
        }
        public event DownloadProgressChangedEventHandler DownloadProgressChanged;
        public event OpenReadCompletedEventHandler OpenReadCompleted;
        #endregion

        #region 读取Xap的有关方法
        private Dictionary<string, Assembly> assemblys = new Dictionary<string, Assembly>();
        public UIElement GetClient(string assemblyName, string InstanceName)
        {
            if (assemblys != null)
                return assemblys[assemblyName].CreateInstance(assemblyName + "." + InstanceName) as UIElement;
            else
                return null;
        }
        private Dictionary<string, Assembly> LoadAssemblyFromXap(Stream packageStream)
        {
            StreamResourceInfo resourceInfo = new StreamResourceInfo(packageStream, null);
            Stream stream = Application.GetResourceStream(resourceInfo, new Uri("AppManifest.xaml", UriKind.Relative)).Stream;
            string appManifestString = new StreamReader(stream).ReadToEnd();
            //assemblys = new Dictionary<string, Assembly>();
            using (XmlReader xmlReader = XmlReader.Create(new StringReader(appManifestString)))
            {
                while (xmlReader.Read())
                {
                    if (xmlReader.IsStartElement("AssemblyPart"))
                    {
                        xmlReader.MoveToAttribute("x:Name");
                        xmlReader.ReadAttributeValue();
                        string xname = xmlReader.Value;
                        xmlReader.MoveToAttribute("Source");
                        xmlReader.ReadAttributeValue();
                        StreamResourceInfo assemblyStream = new StreamResourceInfo(packageStream, "application/binary");
                        StreamResourceInfo si = Application.GetResourceStream(assemblyStream, new Uri(xmlReader.Value, UriKind.Relative));
                        AssemblyPart p = new AssemblyPart();
                        if(!assemblys.ContainsKey(xname))
                            assemblys.Add(xname, p.Load(si.Stream));
                    }
                }
            }
            return assemblys;
        }
        #endregion
    }
}
